import wx
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
# 设置字体
matplotlib.rcParams['font.family'] = 'SimHei'  # 或其他中文字体
matplotlib.rcParams['axes.unicode_minus'] = False  # 使负号正常显示



class SchedulingFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title="调度算法演示", size=(800, 600))

        self.data = None
        self.results = {}

        # 指定CSV文件路径
        self.csv_file_path = r"C:\Users\A\Desktop\processes.csv"

        # 创建菜单栏
        menu_bar = wx.MenuBar()

        file_menu = wx.Menu()
        load_csv_id = file_menu.Append(wx.ID_ANY, "加载指定CSV文件").GetId()
        menu_bar.Append(file_menu, "&文件")

        algorithm_menu = wx.Menu()
        fcfs_id = algorithm_menu.Append(wx.ID_ANY, "FCFS").GetId()
        sjf_id = algorithm_menu.Append(wx.ID_ANY, "SJF").GetId()
        rr_id = algorithm_menu.Append(wx.ID_ANY, "RR").GetId()
        mfq_id = algorithm_menu.Append(wx.ID_ANY, "多级反馈队列").GetId()
        menu_bar.Append(algorithm_menu, "&调度算法")

        prompt_menu = wx.Menu()
        prompt_id = prompt_menu.Append(wx.ID_ANY, "讲程调度(A)").GetId()
        menu_bar.Append(prompt_menu, "&提示词")

        compare_menu = wx.Menu()
        compare_id = compare_menu.Append(wx.ID_ANY, "比较结果").GetId()
        menu_bar.Append(compare_menu, "&比较")

        visualize_menu = wx.Menu()
        visualize_id = visualize_menu.Append(wx.ID_ANY, "可视化调度").GetId()
        menu_bar.Append(visualize_menu, "&模拟")

        self.SetMenuBar(menu_bar)

        # 事件绑定
        self.Bind(wx.EVT_MENU, self.load_specified_csv, id=load_csv_id)
        self.Bind(wx.EVT_MENU, self.on_fcfs, id=fcfs_id)
        self.Bind(wx.EVT_MENU, self.on_sjf, id=sjf_id)
        self.Bind(wx.EVT_MENU, self.on_rr, id=rr_id)
        self.Bind(wx.EVT_MENU, self.on_mfq, id=mfq_id)
        self.Bind(wx.EVT_MENU, self.on_prompt, id=prompt_id)
        self.Bind(wx.EVT_MENU, self.on_compare, id=compare_id)
        self.Bind(wx.EVT_MENU, self.on_visualize, id=visualize_id)

        self.Show()

    def load_specified_csv(self, event):
        print("尝试加载CSV文件")
        try:
            print(f"尝试加载文件: {self.csv_file_path}")
            self.data = pd.read_csv(self.csv_file_path)
            wx.MessageBox(f"成功加载: {self.csv_file_path}", "信息", wx.OK | wx.ICON_INFORMATION)
        except FileNotFoundError:
            wx.MessageBox("文件未找到，请检查文件路径。", "错误", wx.OK | wx.ICON_ERROR)
        except pd.errors.EmptyDataError:
            wx.MessageBox("文件为空，请检查文件内容。", "错误", wx.OK | wx.ICON_ERROR)
        except pd.errors.ParserError:
            wx.MessageBox("文件格式错误，请确保为有效的CSV文件。", "错误", wx.OK | wx.ICON_ERROR)
        except Exception as e:
            wx.MessageBox(f"加载失败: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)

    def on_fcfs(self, event):
        print("执行 FCFS 调度算法")
        if self.data is not None:
            self.data.sort_values('ArrivalTime', inplace=True)
            finish_time = 0
            results = []

            for index, row in self.data.iterrows():
                if finish_time < row['ArrivalTime']:
                    finish_time = row['ArrivalTime']
                finish_time += row['BurstTime']
                turnaround_time = finish_time - row['ArrivalTime']
                waiting_time = turnaround_time - row['BurstTime']
                results.append((row['Process'], turnaround_time, waiting_time))

            self.results['FCFS'] = results
            print("FCFS 结果:", results)
            wx.MessageBox("FCFS 调度完成！", "信息", wx.OK | wx.ICON_INFORMATION)

    def on_sjf(self, event):
        print("执行 SJF 调度算法")
        if self.data is not None:
            self.data.sort_values(['ArrivalTime', 'BurstTime'], inplace=True)
            finish_time = 0
            results = []
            while not self.data.empty:
                ready_queue = self.data[self.data['ArrivalTime'] <= finish_time]
                if not ready_queue.empty:
                    next_process = ready_queue.loc[ready_queue['BurstTime'].idxmin()]
                    self.data.drop(next_process.name, inplace=True)
                else:
                    finish_time = self.data.iloc[0]['ArrivalTime']
                    continue

                finish_time += next_process['BurstTime']
                turnaround_time = finish_time - next_process['ArrivalTime']
                waiting_time = turnaround_time - next_process['BurstTime']
                results.append((next_process['Process'], turnaround_time, waiting_time))

            self.results['SJF'] = results
            print("SJF 结果:", results)
            wx.MessageBox("SJF 调度完成！", "信息", wx.OK | wx.ICON_INFORMATION)

    def on_rr(self, event):
        print("执行 RR 调度算法")
        if self.data is not None:
            time_quantum = 2
            queue = self.data.copy()
            finish_time = 0
            results = []
            waiting_times = {row['Process']: 0 for _, row in self.data.iterrows()}

            while not queue.empty:
                for index, row in queue.iterrows():
                    if row['BurstTime'] > 0:
                        if row['ArrivalTime'] > finish_time:
                            finish_time = row['ArrivalTime']
                        wait_time = max(0, finish_time - row['ArrivalTime'])
                        waiting_times[row['Process']] += wait_time

                        if row['BurstTime'] <= time_quantum:
                            finish_time += row['BurstTime']
                            turnaround_time = finish_time - row['ArrivalTime']
                            waiting_time = turnaround_time - row['BurstTime']
                            results.append((row['Process'], turnaround_time, waiting_time))
                            queue.drop(index, inplace=True)
                        else:
                            finish_time += time_quantum
                            queue.at[index, 'BurstTime'] -= time_quantum
                            # 不要更新 ArrivalTime，保持为原来的到达时间

            self.results['RR'] = results
            print("RR 结果:", results)
            wx.MessageBox("RR 调度完成！", "信息", wx.OK | wx.ICON_INFORMATION)

    def on_mfq(self, event):
        print("执行 多级反馈队列 调度算法")
        if self.data is not None:
            time_quantum1 = 2
            time_quantum2 = 4
            queue1 = self.data.copy()
            queue2 = []
            finish_time = 0
            results = []

            while not queue1.empty or queue2:
                # 第一级队列调度
                for index, row in queue1.iterrows():
                    if row['BurstTime'] > 0:
                        if row['ArrivalTime'] > finish_time:
                            finish_time = row['ArrivalTime']
                        if row['BurstTime'] <= time_quantum1:
                            finish_time += row['BurstTime']
                            turnaround_time = finish_time - row['ArrivalTime']
                            waiting_time = turnaround_time - row['BurstTime']
                            results.append((row['Process'], turnaround_time, waiting_time))
                            queue1.drop(index, inplace=True)
                        else:
                            finish_time += time_quantum1
                            row['BurstTime'] -= time_quantum1
                            queue2.append(row)  # 转移到第二级队列
                            queue1.drop(index, inplace=True)

                # 处理第二级队列
                if queue2:
                    for row in queue2[:]:  # 使用切片遍历以避免在循环中修改列表
                        if row['BurstTime'] > 0:
                            if row['ArrivalTime'] > finish_time:
                                finish_time = row['ArrivalTime']
                            if row['BurstTime'] <= time_quantum2:
                                finish_time += row['BurstTime']
                                turnaround_time = finish_time - row['ArrivalTime']
                                waiting_time = turnaround_time - row['BurstTime']
                                results.append((row['Process'], turnaround_time, waiting_time))
                                queue2.remove(row)
                            else:
                                finish_time += time_quantum2
                                row['BurstTime'] -= time_quantum2
                                queue1.append(row)  # 回到第一级队列

            self.results['MFQ'] = results
            print("多级反馈队列 结果:", results)
            wx.MessageBox("多级反馈队列调度完成！", "信息", wx.OK | wx.ICON_INFORMATION)

    def on_prompt(self, event):
        print("生成调度场景提示词")
        if self.data is not None:
            prompt = "调度场景:\n"
            for index, row in self.data.iterrows():
                prompt += f"进程: {row['Process']}, 到达时间: {row['ArrivalTime']}, 服务时间: {row['BurstTime']}\n"
            wx.MessageBox(prompt, "调度场景提示词", wx.OK | wx.ICON_INFORMATION)

    def on_compare(self, event):
        print("比较结果")
        if len(self.results) >= 2:
            discrepancies = []
            keys = list(self.results.keys())
            for i in range(len(keys) - 1):
                for j in range(i + 1, len(keys)):
                    result1 = self.results[keys[i]]
                    result2 = self.results[keys[j]]
                    for r1, r2 in zip(result1, result2):
                        if r1[1] != r2[1] or r1[2] != r2[2]:
                            discrepancies.append((r1[0], keys[i], r1[1:], keys[j], r2[1:]))
            if discrepancies:
                comparison_result = "\n".join([f"进程: {proc}, {alg1} 结果: {res1}, {alg2} 结果: {res2}"
                                               for proc, alg1, res1, alg2, res2 in discrepancies])
                wx.MessageBox(comparison_result, "比较结果", wx.OK | wx.ICON_WARNING)
            else:
                wx.MessageBox("没有发现差异。", "比较结果", wx.OK | wx.ICON_INFORMATION)
        else:
            wx.MessageBox("需要至少两种调度结果进行比较。", "比较结果", wx.OK | wx.ICON_ERROR)

    def on_visualize(self, event):
        print("可视化调度过程")
        if self.results:
            fig, ax = plt.subplots(figsize=(10, 6))
            for algorithm, result in self.results.items():
                processes = [r[0] for r in result]
                turnaround_times = [r[1] for r in result]
                waiting_times = [r[2] for r in result]

                ax.bar(processes, turnaround_times, label=f'{algorithm} - 周转时间', alpha=0.5)
                ax.bar(processes, waiting_times, label=f'{algorithm} - 等待时间', alpha=0.5, bottom=turnaround_times)

            ax.set_xlabel('进程')
            ax.set_ylabel('时间')
            ax.set_title('调度算法可视化')
            ax.legend()
            plt.show()
        else:
            wx.MessageBox("没有调度结果可视化。", "可视化调度", wx.OK | wx.ICON_ERROR)


if __name__ == "__main__":
    app = wx.App(False)
    frame = SchedulingFrame()
    frame.Show()
    app.MainLoop()
